using System;
using System.Management;

namespace BiztalkConfigLoader
{
    public class BtsAdministration
    {
        #region Private constants
        private const string bts_WMINameSpace = @"root\MicrosoftBizTalkServer";
        private const string bts_HostSettingNameSpace = "MSBTS_HostSetting";
        private const string bts_ServerAppTypeNameSpace = "MSBTS_ServerHost";
        private const string bts_HostInstanceNameSpace = "MSBTS_HostInstance";
        private const string bts_AdapterSettingNameSpace = "MSBTS_AdapterSetting";
        private const string bts_ReceiveHandlerNameSpace = "MSBTS_ReceiveHandler";
        private const string bts_SendHandlerNameSpace = "MSBTS_SendHandler2"; 
        #endregion

        #region Hosts
        public static void AddHost(string hostName, string ntGroupName, bool isDefault, bool hostTracking, bool authTrusted, int hostType, bool isHost32BitOnly)
        {
            PutOptions options = new PutOptions();
            options.Type = PutType.CreateOnly;
            ManagementObject bts_AdminObject;
            // Creating instance of BizTalk Host.
            ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_HostSettingNameSpace, new ObjectGetOptions());
            bts_AdminObject = bts_AdminObjClass.CreateInstance();
            ManagementObject appObject = bts_AdminObject;
            // Assigning Host Properties.
            appObject["Name"] = hostName;
            appObject["NTGroupName"] = ntGroupName;
            appObject["IsDefault"] = isDefault;
            appObject["HostTracking"] = hostTracking;
            appObject["AuthTrusted"] = authTrusted;
            appObject["HostType"] = hostType;
            appObject["IsHost32BitOnly"] = isHost32BitOnly;
            appObject.Put(options);
        }

        public static void RemoveHost(string hostName)
        {
            ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_HostSettingNameSpace, new ObjectGetOptions());
            if (ObjectExists(bts_AdminObjClass, "Name", hostName))
            {
                ManagementObject bts_AdminObject = bts_AdminObjClass.CreateInstance();
                ManagementObject appObject = bts_AdminObject;
                appObject["Name"] = hostName;
                appObject.Delete();
            }
        } 
        #endregion

        #region Host instances
        public static void AddHostInstance(string servername, string hostname, string username, string password, bool startInstance)
        {
            //PutOptions options = new PutOptions();
            //options.Type = PutType.CreateOnly;
            ManagementObject bts_AdminObjectServerHost;
            ManagementObject bts_AdminObjectHostInstance;
            // Creating instance of BizTalk Host.
            ManagementClass bts_AdminObjClassServerHost = new ManagementClass(bts_WMINameSpace, bts_ServerAppTypeNameSpace, new ObjectGetOptions());
            bts_AdminObjectServerHost = bts_AdminObjClassServerHost.CreateInstance();
            bts_AdminObjectServerHost["ServerName"] = servername;
            bts_AdminObjectServerHost["HostName"] = hostname;
            bts_AdminObjectServerHost.InvokeMethod("Map", null);
            ManagementClass bts_AdminObjClassHostInstance = new ManagementClass(bts_WMINameSpace, bts_HostInstanceNameSpace, new ObjectGetOptions());
            bts_AdminObjectHostInstance = bts_AdminObjClassHostInstance.CreateInstance();
            bts_AdminObjectHostInstance["Name"] = "Microsoft BizTalk Server " + hostname + " " + servername;
            object[] objparams = new object[3];
            objparams[0] = username;
            objparams[1] = password;
            objparams[2] = true;
            bts_AdminObjectHostInstance.InvokeMethod("Install", objparams);
            if (startInstance)
            {
                bts_AdminObjectHostInstance.InvokeMethod("Start", null);
            }
        }

        public static void RemoveHostInstance(string servername, string hostname)
        {
            string hostInstanceName = "Microsoft BizTalk Server " + hostname + " " + servername;
            ManagementClass hostInstClass = new ManagementClass(bts_WMINameSpace, bts_HostInstanceNameSpace, new ObjectGetOptions());
            EnumerationOptions enumOptions = new EnumerationOptions();
            enumOptions.ReturnImmediately = false;
            ManagementObjectCollection hostInstCollection = hostInstClass.GetInstances(enumOptions);
            ManagementObject hostInstance = null;
            foreach (ManagementObject inst in hostInstCollection)
            {
                if (inst["Name"] != null)
                {
                    if (inst["Name"].ToString().ToUpper() == hostInstanceName.ToUpper())
                    {
                        hostInstance = inst;
                    }
                }
            }

            if (hostInstance == null)
                return;

            if (hostInstance["HostType"].ToString() != "2" && hostInstance["ServiceState"].ToString() == "4")
            {
                hostInstance.InvokeMethod("Stop", null);
            }


            //Now UnInstall the HostInstance
            hostInstance.InvokeMethod("UnInstall", null);

            //Create an instance of the ServerHost class using the System.Management namespace
            ManagementClass svrHostClass = new ManagementClass(bts_WMINameSpace, bts_ServerAppTypeNameSpace, new ObjectGetOptions());
            ManagementObject svrHostObject = svrHostClass.CreateInstance();

            //Set the properties of the ServerHost instance
            svrHostObject["ServerName"] = servername;
            svrHostObject["HostName"] = hostname;

            //Invoke the UnMap method of the ServerHost object
            svrHostObject.InvokeMethod("UnMap", null);
        } 
        #endregion

        #region Adapters and handlers
        public static void AddAdapter(string name, string type, string comment)
        {
            ManagementObject objInstance = null;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_AdapterSettingNameSpace, new ObjectGetOptions());
            EnumerationOptions enumOptions = new EnumerationOptions();
            enumOptions.ReturnImmediately = false;
            ManagementObjectCollection hostInstCollection = objClass.GetInstances(enumOptions);
            foreach (ManagementObject inst in hostInstCollection)
            {
                if (inst["Name"] != null)
                {
                    if (inst["Name"].ToString().ToUpper() == name.ToUpper())
                    {
                        objInstance = inst;
                    }
                }
            }
            if (objInstance == null)
            {
                objInstance = objClass.CreateInstance();
                objInstance.SetPropertyValue("Name", name);
                objInstance.SetPropertyValue("MgmtCLSID", type);
                objInstance.SetPropertyValue("Comment", comment);
            }
            try
            {
                PutOptions options = new PutOptions() { Type = PutType.UpdateOrCreate };
                objInstance.Put(options);
            }
            catch (Exception)
            {
                return;
            }
        }

        public static void RemoveAdapter(string name)
        {
            ManagementObject objInstance = null;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_AdapterSettingNameSpace, new ObjectGetOptions());
            //Leave the adapter if there are other instances depending on it.
            if (objClass.GetInstances().Count > 0)
                return;
            objInstance = objClass.CreateInstance();
            objInstance.SetPropertyValue("Name", name);
            if (ObjectExists(objClass, "Name", name))
            {
                objInstance.Delete();
            }
        }

        public static void AddReceiveHandler(string adaptername, string hostname)
        {
            ManagementObject objInstance;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveHandlerNameSpace, new ObjectGetOptions());
            objInstance = objClass.CreateInstance();
            objInstance.SetPropertyValue("AdapterName", adaptername);
            objInstance.SetPropertyValue("HostName", hostname);
            objInstance.Put();
        }

        public static void RemoveReceiveHandler(string adaptername, string hostname)
        {
            ManagementObject objInstance;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveHandlerNameSpace, new ObjectGetOptions());
            if (ObjectExists(objClass, "HostName", hostname, "AdapterName", adaptername))
            {
                objInstance = objClass.CreateInstance();
                objInstance.SetPropertyValue("AdapterName", adaptername);
                objInstance.SetPropertyValue("HostName", hostname);
                objInstance.Delete();
            }
        }

        public static void AddSendHandler(string adaptername, string hostname)
        {
            ManagementObject objInstance;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_SendHandlerNameSpace, new ObjectGetOptions());
            objInstance = objClass.CreateInstance();
            objInstance.SetPropertyValue("AdapterName", adaptername);
            objInstance.SetPropertyValue("HostName", hostname);
            objInstance.Put();
        }

        public static void RemoveSendHandler(string adaptername, string hostname)
        {
            ManagementObject objInstance;
            ManagementClass objClass = new ManagementClass(bts_WMINameSpace, bts_SendHandlerNameSpace, new ObjectGetOptions());
            if (ObjectExists(objClass, "HostName", hostname, "AdapterName", adaptername))
            {
                objInstance = objClass.CreateInstance();
                objInstance.SetPropertyValue("AdapterName", adaptername);
                objInstance.SetPropertyValue("HostName", hostname);
                objInstance.Delete();
            }
        } 
        #endregion

        #region ObjectExists
        private static bool ObjectExists(ManagementClass objClass, string key, string value)
        {
            foreach (ManagementObject obj in objClass.GetInstances())
            {
                if (obj[key].ToString() == value)
                    return true;
            }
            return false;
        }

        private static bool ObjectExists(ManagementClass objClass, string key, string value, string key2, string value2)
        {
            foreach (ManagementObject obj in objClass.GetInstances())
            {
                if (obj[key].ToString() == value && obj[key2].ToString() == value2)
                    return true;
            }
            return false;
        } 
        #endregion
    }
}
